<script setup lang="ts">
import { useInitSwiper } from '~/composables/swiper'
import type { Image } from '~/types'

interface Props {
  images: Image[]
  previewWidth: string
  previewHeight: string
  previewHoverable: boolean
  thumbnailCount?: number
  navigator?: boolean
  navigatorPosition?: 'side' | 'cover'
  backgroundVisible?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  thumbnailCount: 5,
  navigator: true,
  navigatorPosition: 'cover',
  previewHoverable: false,
  backgroundVisible: false,
})

const { swiper, init } = useInitSwiper()

const { resolveImgURL } = useGlobalStore()

const imageList = computed(() => props.images.map((img, index) => ({ ...img, index })))

const currentImgIndex = ref(0)
const len = computed(() => imageList.value.length)
const last = computed(() => len.value - 1)
const start = ref(currentImgIndex.value)
const end = computed(() => {
  const e = start.value + props.thumbnailCount
  return e > last.value ? len.value : e
})
const needAdjust = computed(() => len.value > props.thumbnailCount)

const visibleImgList = computed(() => {
  const imgs = imageList.value
  if (end.value > last.value && needAdjust.value) {
    const nextStart = last.value - props.thumbnailCount + 1
    start.value = nextStart < 0 ? 0 : nextStart
  }
  return imgs.slice(start.value, end.value)
})
const tailCount = computed(() => last.value - end.value + 1)

watch(currentImgIndex, (newVal) => {
  swiper.value?.slideTo(newVal)
  if (!needAdjust.value)
    return
  if (newVal >= (start.value + (props.thumbnailCount - 1)))
    start.value += 2
  if (newVal === start.value)
    start.value = start.value < 2 ? 0 : start.value - 2
})

function onSlideChange(e: any) {
  currentImgIndex.value = e.activeIndex
}
defineExpose({
  currentImgIndex,
})
</script>

<template>
  <div>
    <div v-if="backgroundVisible" class="img-bc absolute" :style="{ backgroundImage: `url(${resolveImgURL(images?.[currentImgIndex]?.url)})` }"></div>
    <div relative class="flex items-center justify-center" :class="{ 'px-[60px]': navigatorPosition === 'side' }">
      <div :style="{ width: previewWidth, height: previewHeight }" class="swiper-box">
        <Swiper
          class="h-full w-full"
          :slides-per-view="1"
          :loop="false"
          @swiper="init"
          @slide-change="onSlideChange"
        >
          <SwiperSlide v-for="item in images" :key="item.url">
            <img :class="previewHoverable ? ['transition-all duration-1000 hover:scale-110'] : []" w="full" h="full" object="cover" :src="resolveImgURL(images?.[currentImgIndex]?.url)" />
          </SwiperSlide>
        </Swiper>
      </div>
      <div v-if="navigator && currentImgIndex > 0" class="slide-btn h-[60px] w-[60px] cursor-pointer" :class="[navigatorPosition === 'side' ? 'left-0' : 'left-[16px]']" @click="swiper?.slidePrev()">
        <img src="~/assets/img/icon_prev.png" />
      </div>
      <div v-if="navigator && currentImgIndex < images.length - 1" class="slide-btn h-[60px] w-[60px] cursor-pointer" :class="[navigatorPosition === 'side' ? 'right-0' : 'right-[16px]']" @click="swiper?.slideNext()">
        <img src="~/assets/img/icon_next.png" />
      </div>
    </div>
    <div class="flex justify-center">
      <ul class="imgs mt-[24px] flex" :class="[{ ['has-head']: start > 0, ['has-tail']: tailCount > 0 }]">
        <li
          v-for="(img) in visibleImgList"
          :key="img.url"
          :data-head-count="`+${start}`"
          :data-tail-count="`+${tailCount}`"
          w="[80px] max-md:[40px]" h="[80px] max-md:[40px]" cursor="pointer" rounded="[2px]" :class="{ active: img.index === currentImgIndex }"
          @click="currentImgIndex = img.index"
        >
          <img class="h-full w-full object-cover" :src="resolveImgURL(img.url)" />
        </li>
      </ul>
    </div>
  </div>
</template>

<style lang="postcss" scoped>
.slide-btn {
  @apply absolute z-10 top-[50%];
  transform: translateY(-50%);
}
.swiper-box {
  position: relative;
}
.img-bc {
  background: no-repeat center;
  opacity: 0.1;
  width: 100%;
  height: 100%;
}
.imgs {
  li {
    overflow: hidden;
    border-radius: 2px;
    &.active {
      border: 1px solid var(--primary-color);
    }
  }
  li + li {
    margin-left: 16px;
  }
  &.has-head li:first-child,
  &.has-tail li:last-child {
    position: relative;
    &::after {
      display: flex;
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      background: rgba(0, 0, 0, 0.4);
      color: #fff;
      font-size: 24px;
      font-weight: 500;
    }
  }
  &.has-head li:first-child::after {
    content: attr(data-head-count);
  }
  &.has-tail li:last-child::after {
    content: attr(data-tail-count);
  }
}
</style>
